#include "connexion.h"
#define BUFLEN 255


/**
 * @brief Connexion::Connexion
 * @param IP
 * @param PORT
 * @param username
 * @param password
 *
 * ouvre la socket sur le serveur, et envoie les informations de connexion
 */
Connexion::Connexion(string IP,string PORT,string dlPORT,string username,string password,string path,bool newAccount,QWidget *parent)
{
    socketServer = new MySocket();
    socketServer->myConnect(IP.c_str(),PORT.c_str());
    this->parent = parent;
    Message message;
    if(newAccount)
        message.type='l';
    else
        message.type='L';


    strcpy(message.content.id.username,username.c_str());
    strcpy(message.content.id.password,password.c_str());
    strcpy(message.content.id.dlPort, dlPORT.c_str());

    socketServer->write(&message,sizeof(Message));

    socketServer->read(&message, sizeof(Message));
    switch(message.type)
    {
        case 'O':
            break;

        case 'Q':
            throw -1;
            break;
    }

    startListener(path,dlPORT);

}

void Connexion::startListener(string path,string port)
{
    Listener *sender = new Listener(path,port);
    QThread *senderThread = new QThread(this);

    connect(senderThread, SIGNAL(started()), sender, SLOT(exec()));
    sender->moveToThread(senderThread);

        // Starts an event loop, and emits workerThread->started()
    senderThread->start();
}

vector<FileDescServ> Connexion::searchDesc(string mot)
{
    vector<FileDescServ>files;

    // Demande l'envoie de la liste des fichiers
    Message message;
    uint32_t size = mot.length();
    message.type = 'K';
    socketServer->write(&message, sizeof(Message));
    socketServer->write(&size,sizeof(uint32_t));

    socketServer->write(mot.c_str(), size*sizeof(char));

    socketServer->read(&message, sizeof(Message));

    if(message.type == 'E')
    {

        for(unsigned int i = 0; i<message.content.nbFiles; i++)
        {
            FileDescServ file;
            socketServer->read(&file, sizeof(FileDescServ));
            files.push_back(file);
        }
    }


    return files;
}





/**
 * @brief Connexion::sendFilesList
 *  envoie la liste des fichiers qui sont dans le dossier sur la socket du serveur
 */
void Connexion::sendFilesList(string path)
{
    /**
      envoi de la liste de fichiers
      */
    vector<m_file>files = get_files_name(path.c_str());

    Message message;
    message.type='E';
    message.content.nbFiles=files.size();
    socketServer->write(&message,sizeof(Message));

    DescWindow *fileDesc;
    string desc;

    for(unsigned int i=0;i<files.size();i++)
    {
        /**
         *Recuperation et envoi de la description de chaque fichier
         ***/
        ostringstream nom;
        nom<<path<<"/"<<".desc/"<<files[i].name;
        std::ifstream fichier(nom.str().c_str());
        if ( fichier ) // ce test échoue si le fichier n'est pas ouvert
        {
              std::stringstream buffer; // variable contenant l'intégralité du fichier
              // copier l'intégralité du fichier dans le buffer
              buffer << fichier.rdbuf();
              desc=buffer.str();
        }
        else
        {
            fileDesc=new DescWindow(parent,files[i].name);
            fileDesc->exec();
            desc= fileDesc->getDesc();

            ofstream SaveFile(nom.str().c_str(), ios::ate | ios::trunc | ios::binary);
            SaveFile<<desc;
            SaveFile.close();
        }

        FileDescCli fileDesc;
        strcpy(fileDesc.name,files[i].name.c_str());
        fileDesc.size=files[i].size;
        fileDesc.descSize=desc.length();

        socketServer->write(&fileDesc,sizeof(FileDescCli));

        if(desc.length()>0)
        {
            socketServer->write(desc.c_str(), desc.length());
        }
    }


 }


/**
    Renvoi la liste des noms des fichiers du repertoire

  */
vector<m_file> Connexion::get_files_name(string dirn)
{
        vector<m_file> files;
        m_file file;
        ostringstream nom;
        DIR *dir = NULL;
        struct dirent *drnt = NULL;

        struct stat filestatus;
        string point = ".";
        string pointpoint="..";
        dir=opendir(dirn.c_str());
        if(dir)
        {
               while((drnt = readdir(dir)))
                {
                   if(drnt->d_name[0]!='.')  // on affiche plus ce qui commence par un .
                    {

                     /**
                      *recuperation de la taille et du nom des fichiers
                      */
                        file.name = drnt->d_name;
                        nom<<dirn<<"/"<< drnt->d_name;
                        stat(nom.str().c_str(), &filestatus );
                        file.size = filestatus.st_size;
                        files.push_back(file);
                        nom.str("");


                   }
                }
                closedir(dir);
        }
        else
        {
                printf("Can not open directory \n");
        }

        return files;


}


/**
 *Recuperation de la liste de fichier dans un vector de string
 */
vector<FileDescServ> Connexion::getFilesList()
{
    vector<FileDescServ>files;

    // Demande l'envoie de la liste des fichiers
    Message message;
    message.type = 'A';
    socketServer->write(&message, sizeof(Message));

    socketServer->read(&message, sizeof(Message));

    if(message.type == 'E')
    {

        for(unsigned int i = 0; i<message.content.nbFiles; i++)
        {
            FileDescServ file;
            socketServer->read(&file, sizeof(FileDescServ));
            files.push_back(file);
        }
    }

    return files;
}

Connection Connexion::request_connection(string fileName, string author)
{
    Message message;
    message.type = 'C';

    strcpy(message.content.file.name, fileName.c_str());
    strcpy(message.content.file.author, author.c_str());

    socketServer->write(&message, sizeof(Message));

    socketServer->read(&message, sizeof(Message));

    if(message.type == 'I')
    {
        return message.content.connection;
    }
    else
    {
        throw -1;
    }
}

void Connexion::logout()
{
    Message message;
    string desc;
    message.type = 'Q';
    socketServer->write(&message, sizeof(Message));
}

char* Connexion::getDesc(string name,string author)
{
    Message message;
    char * desc = NULL;
    uint32_t size;
    message.type = 'D';

    strcpy(message.content.file.name, name.c_str());
    strcpy(message.content.file.author, author.c_str());

    socketServer->write(&message, sizeof(Message));

    socketServer->read(&size, sizeof(uint32_t));
    desc = new char[size+1];
    desc[size]='\0';

    socketServer->read(desc, size*sizeof(char));


    return desc;

}
